/*
 * Galaxium Messenger
 * Copyright (C) 2007 Paul Burton <paulburton89@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.Collections.Generic;
using System.Text;

using Anculus.Core;

using Galaxium.Core;

namespace Galaxium.Protocol.Msn
{
	public class MIMECollection: OrderedDictionary<string, MIMEValue>
	{
		public new MIMEValue this [string name]
		{
			get
			{
				if (!ContainsKey (name))
					return new MIMEValue ();
				
				return base[name];
			}
			set { base[name] = value; }
		}
		
		public MIMECollection ()
			: base ()
		{
		}
		
		public MIMECollection (byte[] data)
			: this ()
		{
			Parse (data);
		}
		
		public int Parse (byte[] data)
		{
			int end = MsnByteArrayUtility.IndexOf (data, "\r\n\r\n");
			int ret = end;
			
			if (end < 0)
				ret = end = data.Length;
			else
				ret += 4;
			
			byte[] mimeData = new byte[end];
			Array.Copy (data, mimeData, end);
			
			string mimeStr = Encoding.UTF8.GetString (mimeData);
			string[] lines = mimeStr.Trim ().Split (new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
			
			int i = 0;
			while (i < lines.Length)
			{
				string line = lines[i];
				
				while ((++i < lines.Length) && lines[i].StartsWith ("\t"))
					line += lines[i];
				
				int nameEnd = line.IndexOf (":");
				
				if (nameEnd < 0)
					continue;
				
				string name = line.Substring (0, nameEnd).Trim ();
				MIMEValue val = line.Substring (nameEnd + 1).Trim ();
				
				this[name] = val;
			}
			
			return ret;
		}
		
		public override string ToString ()
		{
			StringBuilder sb = new StringBuilder ();
			
			foreach (KeyValuePair<string, MIMEValue> pair in this)
			{
				sb.Append (pair.Key);
				sb.Append (": ");
				sb.Append (pair.Value.ToString ());
				sb.Append ("\r\n");
			}
			
			return sb.ToString ();
		}
	}
	
	public class MIMEValue
	{
		string _val;
		OrderedDictionary<object, string> _attributes = new OrderedDictionary<object, string> ();
		
		public string Value
		{
			get { return _val; }
		}
		
		MIMEValue (string main, OrderedDictionary<object, string> attributes)
		{
			ThrowUtility.ThrowIfNull ("attributes", attributes);
			
			_val = main;
			_attributes = attributes;
		}
		
		public MIMEValue (string main)
		{
			_val = main;
		}
		
		public MIMEValue ()
		{
			_val = string.Empty;
		}
		
		public string this [object attKey]
		{
			get
			{
				if (!_attributes.ContainsKey (attKey))
					return string.Empty;
				
				return _attributes[attKey];
			}
			set { _attributes[attKey] = value; }
		}
		
		public static implicit operator string (MIMEValue val)
        {
			return val.ToString ();
        }
		
		public static implicit operator MIMEValue (string str)
		{
			if (str == null)
				str = string.Empty;
			
			str = str.Trim ();
			
			string main = str;
			OrderedDictionary<object, string> attributes = new OrderedDictionary<object, string> ();
			
			if (main.Contains (";"))
			{
				main = main.Substring (0, main.IndexOf (";")).Trim ();				
				str = str.Substring (str.IndexOf (";") + 1);
				
				string[] parameters = str.Split (';');

				int i = 0;
				foreach (string param in parameters)
				{
					int index = param.IndexOf ('=');

					object key = i++;
					string val = string.Empty;
					
					if (index > 0)
					{
						key = param.Substring (0, index).Trim ();
						val = param.Substring (index + 1).Trim ();
					}
					
					attributes[key] = val;
				}
			}
			
			return new MIMEValue (main, attributes);
		}
		
		public void ClearAttributes ()
		{
			_attributes.Clear ();
		}
		
		public bool HasAttribute (string name)
		{
			return _attributes.ContainsKey (name);
		}
		
		public override string ToString ()
		{
			string str = _val;
			
			foreach (KeyValuePair<object, string> att in _attributes)
			{
				if (!string.IsNullOrEmpty (str))
					str += ";";
				
				if (att.Key is int)
					str += att.Value;
				else
					str += string.Format ("{0}={1}", att.Key, att.Value);
			}
			
			return str.Trim ();
		}
	}
}
